home *** CD-ROM | disk | FTP | other *** search
/ ftp.mactech.com 2010 / ftp.mactech.com.tar / ftp.mactech.com / macintosh-c / macc-carbon-demos-nonbinhex.sit / macc-carbon-demos-nonbinhex / chap24-demo-classic events / SoundAndSpeech.c < prev    next >
C/C++ Source or Header  |  2001-05-31  |  15KB  |  551 lines

  1. // *******************************************************************************************
  2. // SoundAndSpeech.c                                                        CLASSIC EVENT MODEL
  3. // *******************************************************************************************
  4. //
  5. // This program opens a modeless dialog containing five bevel button controls arranged in
  6. // two groups, namely, a synchronous sound group and an asynchronous sound group.  Clicking on
  7. // the bevel buttons causes sound to be played back or recorded as follows:
  8. //
  9. // •    Synchronous group:
  10. //
  11. //        •  Play sound resource.
  12. //
  13. //        •  Record sound resource (Mac OS 8/9 only).
  14. //
  15. //        •  Speak text string.
  16. //
  17. // •    Asynchronous group:
  18. //
  19. //        •  Play sound resource.
  20. //
  21. //        •  Speak text string.
  22. //
  23. // The asynchronous sound sections of the program utilise a special library called
  24. // AsyncSoundLibPPC, which must be included in the CodeWarrior project.
  25. //
  26. // The program utilises the following resources:
  27. //
  28. // •    A 'plst' resource.
  29. //
  30. // •    A 'DLOG' resource and associated 'DITL', 'dlgx', and 'dftb' resources (all purgeable).
  31. //
  32. // •    'CNTL' resources (purgeable) for the controls within the dialog.
  33. //
  34. // •    Two 'snd ' resources, one for synchronous playback (purgeable) and one for asynchronous
  35. //        playback (purgeable).
  36. //
  37. // •    Four 'cicn' resources (purgeable).  Two are used to provide an animated display which
  38. //        halts during synchronous playback and continues during asynchronous playback.  The
  39. //        remaining two are used by the bevel button controls.
  40. //
  41. // •    Two 'STR#' resources containing "speak text" strings and error message strings (all
  42. //        purgeable).
  43. //
  44. // •    'hrct' and 'hwin' resources (purgeable) for balloon help.
  45. //
  46. // •    A 'SIZE' resource with the acceptSuspendResumeEvents, canBackground, 
  47. //        doesActivateOnFGSwitch, and isHighLevelEventAware flags set.
  48. //
  49. // Each time it is invoked, the function doRecordResource creates a new 'snd' resource with a
  50. // unique ID in the resource fork of a file titled "SoundResources".
  51. //
  52. // *******************************************************************************************
  53.  
  54. // ………………………………………………………………………………………………………………………………………………………………………………………………………………………… includes
  55.  
  56. #include <Carbon.h>
  57. #include <string.h>
  58.  
  59. // …………………………………………………………………………………………………………………………………………………………………………………………………………………………… defines
  60.  
  61. #define rDialog                                    128
  62. #define  iDone                                    1
  63. #define  iPlayResourceSync            4
  64. #define  iRecordResource                5
  65. #define  iSpeakTextSync                    6
  66. #define  iPlayResourceASync            7    
  67. #define  iSpeakTextAsync                8
  68. #define rPlaySoundResourceSync    8192
  69. #define rPlaySoundResourceASync    8193
  70. #define rSpeechStrings                    128
  71. #define rErrorStrings                        129
  72. #define  eOpenDialogFail                1
  73. #define  eCannotInitialise            2
  74. #define  eGetResource                        3
  75. #define  eMemory                                4
  76. #define  eMakeFSSpec                        5
  77. #define  eWriteResource                    6
  78. #define  eNoChannelsAvailable        7
  79. #define  ePlaySound                            8
  80. #define  eSndPlay                                9        
  81. #define  eSndRecord                            10
  82. #define  eSpeakString                        11
  83. #define rColourIcon1                        128
  84. #define rColourIcon2                        129
  85. #define kMaxChannels                        8
  86. #define kOutOfChannels                    1
  87.  
  88. // …………………………………………………………………………………………………………………………………………………………………………………………………… global variables
  89.  
  90. Boolean        gRunningOnX = false;
  91. Boolean        gDone;
  92. DialogRef    gDialogRef;
  93.  
  94. // .............................................................. AsyncSoundLib attention flag
  95.  
  96. Boolean    gCallAS_CloseChannel = false;
  97.  
  98. // …………………………………………………………………………………………………………………………………………………………………………………………… function prototypes
  99.  
  100. void    main                                    (void);
  101. void    doPreliminaries                (void);
  102. OSErr    quitAppEventHandler        (AppleEvent *,AppleEvent *,SInt32);
  103. void    doInitialiseSoundLib    (void);
  104. void    eventLoop                            (void);
  105. void    doDialogHit                        (SInt16);
  106. void  doPlayResourceSync        (void);
  107. void    doRecordResource            (void);
  108. void    doSpeakStringSync            (void);
  109. void    doPlayResourceASync        (void);
  110. void    doSpeakStringAsync        (void);
  111. void    doSetUpDialog                    (void);
  112. void    doErrorAlert                    (SInt16);
  113. void    helpTags                            (DialogRef);
  114.  
  115. // ……………………………………………………………………………………………………………………………………………………… AsyncSoundLib function prototypes
  116.  
  117. OSErr    AS_Initialise        (Boolean *,SInt16);
  118. OSErr    AS_GetChannel        (SInt32,SndChannelPtr *);
  119. OSErr    AS_PlayID                (SInt16, SInt32 *);
  120. OSErr    AS_PlayHandle        (Handle,SInt32 *);
  121. void    AS_CloseChannel    (void);
  122. void    AS_CloseDown        (void);
  123.  
  124. // ************************************************************************************** main
  125.  
  126. void main(void)
  127. {
  128.     SInt32    response;
  129.  
  130.     // ……………………………………………………………………………………………………………………………………………………………………………………………… do preliminaries
  131.  
  132.     doPreliminaries();
  133.  
  134.     // ……………………………………………………………………………………………………………… disable Quit item in Mac OS X Application menu
  135.  
  136.     DisableMenuCommand(NULL,'quit');
  137.  
  138.     // ……………………………………………………………………………………………………………………………………………………………………………… open and set up dialog
  139.  
  140.     if(!(gDialogRef = GetNewDialog(rDialog,NULL,(WindowRef) -1)))
  141.     {
  142.         doErrorAlert(eOpenDialogFail);
  143.         ExitToShell();
  144.     }
  145.  
  146.     SetPortDialogPort(gDialogRef);
  147.     SetDialogDefaultItem(gDialogRef,kStdOkItemIndex);
  148.  
  149.     Gestalt(gestaltMenuMgrAttr,&response);
  150.     if(response & gestaltMenuMgrAquaLayoutMask)
  151.     {
  152.         helpTags(gDialogRef);
  153.         gRunningOnX = true;
  154.     }
  155.  
  156.     doSetUpDialog();
  157.  
  158.     ShowWindow(GetDialogWindow(gDialogRef));
  159.     // ………………………………………………………………………………………………………………………………………………………………………… initialise AsyncSoundLib
  160.  
  161.     doInitialiseSoundLib();
  162.  
  163.     // ……………………………………………………………………………………………………………………………………………………………………………………………… enter event loop
  164.  
  165.     eventLoop();
  166. }
  167.  
  168. // *************************************************************************** doPreliminaries
  169.  
  170. void  doPreliminaries(void)
  171. {
  172.     OSErr    osError;
  173.  
  174.     MoreMasterPointers(64);
  175.     InitCursor();
  176.     FlushEvents(everyEvent,0);
  177.  
  178.     osError = AEInstallEventHandler(kCoreEventClass,kAEQuitApplication,
  179.                                                         NewAEEventHandlerUPP((AEEventHandlerProcPtr) quitAppEventHandler),
  180.                                                         0L,false);
  181.     if(osError != noErr)
  182.         ExitToShell();
  183. }
  184.  
  185. // **************************************************************************** doQuitAppEvent
  186.  
  187. OSErr  quitAppEventHandler(AppleEvent *appEvent,AppleEvent *reply,SInt32 handlerRefcon)
  188. {
  189.     OSErr            osError;
  190.     DescType    returnedType;
  191.     Size            actualSize;
  192.  
  193.     osError = AEGetAttributePtr(appEvent,keyMissedKeywordAttr,typeWildCard,&returnedType,NULL,0,
  194.                                                             &actualSize);
  195.  
  196.     if(osError == errAEDescNotFound)
  197.     {
  198.         gDone = true;
  199.         osError = noErr;
  200.     } 
  201.     else if(osError == noErr)
  202.         osError = errAEParamMissed;
  203.  
  204.     return osError;
  205. }
  206.  
  207. // ********************************************************************** doInitialiseSoundLib
  208.  
  209. void  doInitialiseSoundLib(void)
  210. {
  211.     if(AS_Initialise(&gCallAS_CloseChannel,kMaxChannels) != noErr)
  212.     {
  213.         doErrorAlert(eCannotInitialise);
  214.         ExitToShell();
  215.     }
  216. }
  217.  
  218. // ********************************************************************************* eventLoop
  219.  
  220. void  eventLoop(void)
  221. {
  222.     Rect                theRect, eraseRect;
  223.     CIconHandle    colourIconHdl1;
  224.     CIconHandle    colourIconHdl2;
  225.     SInt16            fontNum, itemHit;
  226.     UInt32             finalTicks;
  227.     Boolean            gotEvent;
  228.     EventRecord    eventStructure;
  229.     DialogRef        theDialogRef;
  230.     WindowRef     windowRef;
  231.     SInt16            partCode;
  232.  
  233.     SetRect(&theRect,262,169,294,201);
  234.     SetRect(&eraseRect,310,170,481,200);
  235.     colourIconHdl1 = GetCIcon(rColourIcon1);
  236.     colourIconHdl2 = GetCIcon(rColourIcon2);
  237.  
  238.     gDone = false;
  239.  
  240.     while(!gDone) 
  241.     {
  242.         if(gCallAS_CloseChannel)
  243.         {
  244.             AS_CloseChannel();
  245.  
  246.             GetFNum("\pGeneva",&fontNum);
  247.             TextFont(fontNum);
  248.             TextSize(10);
  249.             MoveTo(341,189);
  250.             DrawString("\pAS_CloseChannel called");
  251.             QDFlushPortBuffer(GetWindowPort(FrontWindow()),NULL);
  252.             Delay(45,&finalTicks);
  253.         }
  254.  
  255.         gotEvent = WaitNextEvent(everyEvent,&eventStructure,10,NULL);
  256.  
  257.         if(gotEvent)
  258.         {
  259.             if(IsDialogEvent(&eventStructure))
  260.             {
  261.                 if(DialogSelect(&eventStructure,&theDialogRef,&itemHit))
  262.                     doDialogHit(itemHit);
  263.             }
  264.             else
  265.             {
  266.                 if(eventStructure.what == mouseDown)
  267.                 {
  268.                     partCode = FindWindow(eventStructure.where,&windowRef);
  269.                     if(partCode == inDrag)
  270.                         DragWindow(windowRef,eventStructure.where,NULL);
  271.                     if(partCode == inMenuBar)
  272.                         MenuSelect(eventStructure.where);
  273.                 }
  274.             }
  275.         }
  276.         else
  277.         {
  278.             PlotCIcon(&theRect,colourIconHdl1);
  279.             QDFlushPortBuffer(GetDialogPort(gDialogRef),NULL);
  280.             Delay(5,&finalTicks);
  281.             PlotCIcon(&theRect,colourIconHdl2);
  282.             Delay(5,&finalTicks);
  283.             EraseRect(&eraseRect);
  284.         }
  285.     }
  286.  
  287.     DisposeDialog(gDialogRef);
  288.  
  289.     AS_CloseDown();
  290. }
  291.  
  292. // ******************************************************************************* doDialogHit
  293.  
  294. void  doDialogHit(SInt16 item)
  295. {
  296.     switch(item) 
  297.     {
  298.         case iDone:
  299.             gDone = true;
  300.             break;
  301.  
  302.         case iPlayResourceSync:
  303.             doPlayResourceSync();
  304.             break;
  305.  
  306.         case iRecordResource:
  307.             doRecordResource();
  308.             break;
  309.  
  310.         case iSpeakTextSync:
  311.             doSpeakStringSync();
  312.             break;
  313.  
  314.         case iPlayResourceASync:
  315.             doPlayResourceASync();
  316.             break;
  317.  
  318.         case iSpeakTextAsync:
  319.             doSpeakStringAsync();
  320.             break;
  321.     }
  322. }
  323.  
  324. // ************************************************************************ doPlayResourceSync
  325.  
  326. void  doPlayResourceSync(void)
  327. {
  328.     SndListHandle    sndListHdl;
  329.     SInt16                resErr;
  330.     OSErr                    osErr;
  331.     ControlRef        controlRef;
  332.  
  333.     sndListHdl = (SndListHandle) GetResource('snd ',rPlaySoundResourceSync);
  334.     resErr = ResError();
  335.     if(resErr != noErr)
  336.         doErrorAlert(eGetResource);
  337.  
  338.     if(sndListHdl != NULL)
  339.     {
  340.         HLock((Handle) sndListHdl);
  341.         osErr = SndPlay(NULL,sndListHdl,false);
  342.         if(osErr != noErr)
  343.             doErrorAlert(eSndPlay);
  344.         HUnlock((Handle) sndListHdl);
  345.         ReleaseResource((Handle) sndListHdl);
  346.  
  347.         GetDialogItemAsControl(gDialogRef,iPlayResourceSync,&controlRef);
  348.         SetControlValue(controlRef,0);
  349.     }
  350. }
  351.  
  352. // ************************************************************************** doRecordResource
  353.  
  354. void  doRecordResource(void)
  355. {
  356.     SInt16            oldResFileRefNum, theResourceID, resErr, tempResFileRefNum;
  357.     BitMap            screenBits;
  358.     Point                topLeft;
  359.     OSErr                memErr, osErr;
  360.     Handle            soundHdl;
  361.     FSSpec            fileSpecTemp;
  362.     ControlRef    controlRef;
  363.  
  364.     oldResFileRefNum = CurResFile();
  365.  
  366.     GetQDGlobalsScreenBits(&screenBits);
  367.     topLeft.h = (screenBits.bounds.right / 2) - 156;
  368.     topLeft.v = 150;
  369.     
  370.     soundHdl = NewHandle(25000);
  371.     memErr = MemError();
  372.     if(memErr != noErr)
  373.     {
  374.         doErrorAlert(eMemory);
  375.         return;
  376.     }
  377.  
  378.     osErr = FSMakeFSSpec(0,0,"\pSoundResources",&fileSpecTemp);
  379.     if(osErr == noErr)
  380.     {
  381.         tempResFileRefNum = FSpOpenResFile(&fileSpecTemp,fsWrPerm);
  382.         UseResFile(tempResFileRefNum);
  383.     }
  384.     else
  385.         doErrorAlert(eMakeFSSpec);
  386.  
  387.     if(osErr == noErr)
  388.     {
  389.         osErr = SndRecord(NULL,topLeft,siBetterQuality,&(SndListHandle) soundHdl);
  390.         if(osErr != noErr && osErr != userCanceledErr)
  391.             doErrorAlert(eSndRecord);
  392.         else if(osErr != userCanceledErr)
  393.         {
  394.             do
  395.             {
  396.                 theResourceID = UniqueID('snd ');
  397.             } while(theResourceID <= 8191 && theResourceID >= 0);
  398.  
  399.             AddResource(soundHdl,'snd ',theResourceID,"\pTest");
  400.             resErr = ResError();
  401.             if(resErr == noErr)
  402.                 UpdateResFile(tempResFileRefNum);
  403.             resErr = ResError();
  404.             if(resErr != noErr)
  405.                 doErrorAlert(eWriteResource);
  406.         }
  407.         
  408.         CloseResFile(tempResFileRefNum);
  409.     }
  410.  
  411.     DisposeHandle(soundHdl);
  412.     UseResFile(oldResFileRefNum);
  413.  
  414.     GetDialogItemAsControl(gDialogRef,iRecordResource,&controlRef);
  415.     SetControlValue(controlRef,0);
  416. }
  417.  
  418. // ************************************************************************* doSpeakStringSync
  419.  
  420. void  doSpeakStringSync(void)
  421. {
  422.     SInt16            activeChannels;
  423.     Str255            theString;
  424.     OSErr                resErr, osErr;
  425.     ControlRef    controlRef;
  426.  
  427.     activeChannels = SpeechBusy();
  428.  
  429.     GetIndString(theString,rSpeechStrings,1);
  430.     resErr = ResError();
  431.     if(resErr != noErr)
  432.     {
  433.         doErrorAlert(eGetResource);
  434.         return;
  435.     }
  436.  
  437.     osErr = SpeakString(theString);
  438.     if(osErr != noErr)
  439.         doErrorAlert(eSpeakString);
  440.  
  441.     while(SpeechBusy() != activeChannels)
  442.         ;
  443.  
  444.     GetDialogItemAsControl(gDialogRef,iSpeakTextSync,&controlRef);
  445.     SetControlValue(controlRef,0);
  446. }
  447.  
  448. // *********************************************************************** doPlayResourceASync
  449.  
  450. void  doPlayResourceASync(void)
  451. {
  452.     SInt16    error;
  453.  
  454.     error = AS_PlayID(rPlaySoundResourceASync,NULL);
  455.     if(error == kOutOfChannels)
  456.         doErrorAlert(eNoChannelsAvailable);
  457.     else
  458.         if(error != noErr)
  459.             doErrorAlert(ePlaySound);
  460. }
  461.  
  462. // ************************************************************************ doSpeakStringAsync
  463.  
  464. void  doSpeakStringAsync(void)
  465. {
  466.     Str255    theString;
  467.     OSErr        resErr, osErr;
  468.  
  469.     GetIndString(theString,rSpeechStrings,2);
  470.     resErr = ResError();
  471.     if(resErr != noErr)
  472.     {
  473.         doErrorAlert(eGetResource);
  474.         return;
  475.     }
  476.  
  477.     osErr = SpeakString(theString);
  478.     if(osErr != noErr)
  479.         doErrorAlert(eSpeakString);
  480. }
  481.  
  482. // ***************************************************************************** doSetUpDialog
  483.  
  484. void  doSetUpDialog(void)
  485. {
  486.     SInt16                                                a;
  487.     Point                                                    offset;
  488.     ControlRef                                        controlRef;
  489.     ControlButtonGraphicAlignment    alignConstant = kControlBevelButtonAlignLeft;
  490.     ControlButtonTextPlacement        placeConstant = kControlBevelButtonPlaceToRightOfGraphic;
  491.  
  492.     offset.v = 1;
  493.     offset.h = 5;
  494.  
  495.     for(a=iPlayResourceSync;a<iSpeakTextAsync+1;a++)
  496.     {
  497.         GetDialogItemAsControl(gDialogRef,a,&controlRef);
  498.         SetControlData(controlRef,kControlEntireControl,kControlBevelButtonGraphicAlignTag,
  499.                                      sizeof(alignConstant),&alignConstant);
  500.         SetControlData(controlRef,kControlEntireControl,kControlBevelButtonGraphicOffsetTag,
  501.                                      sizeof(offset),&offset);
  502.         SetControlData(controlRef,kControlEntireControl,kControlBevelButtonTextPlaceTag,
  503.                                     sizeof(placeConstant),&placeConstant);
  504.     }
  505.     if(gRunningOnX)
  506.     {
  507.         GetDialogItemAsControl(gDialogRef,iRecordResource,&controlRef);
  508.         DeactivateControl(controlRef);
  509.     }
  510. }
  511.  
  512. // ****************************************************************************** doErrorAlert
  513.  
  514. void  doErrorAlert(SInt16 errorStringIndex)
  515. {
  516.     Str255    errorString;
  517.     SInt16    itemHit;
  518.  
  519.     GetIndString(errorString,rErrorStrings,errorStringIndex);
  520.  
  521.     StandardAlert(kAlertCautionAlert,errorString,NULL,NULL,&itemHit);
  522. }
  523.  
  524. // ********************************************************************************** helpTags
  525.  
  526. void  helpTags(DialogRef dialogRef)
  527. {
  528.     HMHelpContentRec    helpContent;
  529.     SInt16                        a;
  530.     ControlRef                controlRef;
  531.  
  532.   memset(&helpContent,0,sizeof(helpContent));
  533.   HMSetTagDelay(500);
  534.   HMSetHelpTagsDisplayed(true);
  535.  
  536.     helpContent.version = kMacHelpVersion;
  537.     helpContent.tagSide = kHMOutsideTopCenterAligned;
  538.     helpContent.content[kHMMinimumContentIndex].contentType = kHMStringResContent;
  539.     helpContent.content[kHMMinimumContentIndex].u.tagStringRes.hmmResID = 130;
  540.  
  541.     for(a = 1;a <= 5; a++)
  542.     {
  543.         if(a == 2)
  544.             continue;
  545.         helpContent.content[kHMMinimumContentIndex].u.tagStringRes.hmmIndex = a;
  546.         GetDialogItemAsControl(dialogRef,a + 3,&controlRef);
  547.         HMSetControlHelpContent(controlRef,&helpContent);
  548.     }
  549. }
  550.  
  551. // *******************************************************************************************